#include <game.h>

coeur::coeur() : base("coeur")
{
	in = new interface;
	co = new console;

	currentChap = new chap;
	currentLieu = new lieu;
	currentLocal = new local;
	mylogger = new logger;

	pathChap = new string<stringc*>;
	pathLieu = new string<stringc*>;
	pathLocal = new string<stringc*>;

	dr = EDT_NULL;
	dim = dimension2d<s32>(640, 480);
	bits = 8;
	fullscreen = false;
	stencilbuffer = false;
	vsync = false;

	lang = 0;
}

coeur::~coeur()
{
	delete pathLocal;
	delete pathLieu;
	delete pathChap;

	delete currentLocal;
	delete currentLieu;
	delete currentChap;

	delete co;
	delete in;
}

int coeur::init(stringc pathConfig)
{
	device = createDevice(dr,dim,bits,fullscreen,stencilbuffer,vsync);

	stringc pathMain = "";

	IXMLReader* xmlConfig = device->getFileSystem()->createXMLReader("xml/config.xml");

	while(xmlConfig && xmlConfig->read())
	{
		if (xmlConfig->getNodeType()==EXN_ELEMENT)
		{
			if (core::stringw("device") == xmlConfig->getNodeName())
			{
				dr = E_DRIVER_TYPE(xmlConfig->getAttributeValueAsInt(L"driver"));
			}
			else if (core::stringw("dimension") == xmlConfig->getNodeName())
			{
				dim = dimension2d<s32>(xmlConfig->getAttributeValueAsInt(L"width"),xmlConfig->getAttributeValueAsInt(L"height"));
			}
			else if (core::stringw("pixel") == xmlConfig->getNodeName())
			{
				bits = xmlConfig->getAttributeValueAsInt(L"bits");
			}
			else if (core::stringw("fullscreen") == xmlConfig->getNodeName())
			{
				fullscreen = xmlConfig->getAttributeValueAsInt(L"fs");
			}
			else if (core::stringw("stencilbuffer") == xmlConfig->getNodeName())
			{
				stencilbuffer = xmlConfig->getAttributeValueAsInt(L"sb");
			}
			else if (core::stringw("vsync") == xmlConfig->getNodeName())
			{
				vsync = xmlConfig->getAttributeValueAsInt(L"vs");
			}
			else if (core::stringw("local") == xmlConfig->getNodeName())
			{
				lang = xmlConfig->getAttributeValueAsInt(L"lang");
			}
			else if (core::stringw("main") == xmlConfig->getNodeName())
			{
				pathMain = xmlConfig->getAttributeValue(L"file");
			}
		}
	}

	xmlConfig->drop();

	device->drop();

	device = createDevice(dr,dim,bits,fullscreen,stencilbuffer,vsync);
	engine = createIrrKlangDevice();

	driver = device->getVideoDriver();
	smgr = device->getSceneManager();
	env = device->getGUIEnvironment();

	mylogger->init(this,device->getFileSystem());
	base::init(0,this);

	log(stringc("Main xml : ") + pathMain + " loading ...");

	IXMLReader* xmlMain = device->getFileSystem()->createXMLReader(pathMain.c_str());

	stringc pathInterface = "";
	
	while(xmlMain && xmlMain->read())
	{
		if (xmlMain->getNodeType()==EXN_ELEMENT)
		{
			if (core::stringw("interface") == xmlMain->getNodeName())
			{
				pathInterface = xmlMain->getAttributeValue(L"file");
				log( stringc("pathInterface : ") + pathInterface.c_str());
			}
			else if (core::stringw("chap") == xmlMain->getNodeName())
			{
				pathChap->append(new stringc(xmlMain->getAttributeValue(L"file")));
				log( stringc("pathChap : ") + pathInterface.c_str());
			}
			else if (core::stringw("lieu") == xmlMain->getNodeName())
			{
				pathLieu->append(new stringc(xmlMain->getAttributeValue(L"file")));
				log( stringc("pathLieu : ") + (*pathLieu)[pathLieu->size()-1]->c_str());
			}
			else if (core::stringw("local") == xmlMain->getNodeName())
			{
				pathLocal->append(new stringc(xmlMain->getAttributeValue(L"file")));
				log( stringc("pathLocal : ") + (*pathLocal)[pathLocal->size()-1]->c_str());
			}
		}
	}

	xmlMain->drop();

	metaSelector = smgr->createMetaTriangleSelector();
	
	cam = smgr->addCameraSceneNodeFPS();
	cam->setPosition(vector3df(0,100,-200));
	device->getCursorControl()->setVisible(false);
	log("Camera ajoute");

	/*smgr->addSphereSceneNode(10,16,*/smgr->addLightSceneNode(0,vector3df(0,190,0))/*)*/;
	log("Light ajoute");
	
	q = false;

	IXMLReader* xmlInterface = device->getFileSystem()->createXMLReader(pathInterface.c_str());
	in->init(this,env,xmlInterface,0);
	xmlInterface->drop();
	log("Interface initialized");

	loadChap(0);
	log("Chapitre load");
	loadLocal(lang);
	log("Local load");

	setCaption(currentLocal->getCaption());

	co->init(this,env);
	log("Console initialized");

	device->setEventReceiver(this);
	log("Event receiver on");

	ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(metaSelector, cam, vector3df(40,80,40), vector3df(0,-980,0), vector3df(0,70,0));
	cam->addAnimator(anim);
	anim->drop();

	return 1;
}

int coeur::update()
{
	int r = device->run();
	if (r && device->isWindowActive())
	{
		curPos=device->getCursorControl()->getPosition();
		selectedAction = getActionMesh(smgr->getSceneCollisionManager()->getSceneNodeFromScreenCoordinatesBB(curPos,65280));
		in->update();
		co->update();
		driver->beginScene(true, true, SColor(0,100,100,140));
		
		smgr->drawAll();
		env->drawAll();
		
		driver->endScene();
		if (q)
		{
			log("Quitting");
			return 0;
		}
	}
	return r;
}

int coeur::close()
{
	co->close();
	currentLocal->close();
	currentLieu->close();
	currentChap->close();
	in->close();
	log("All subclass closed");
	log("Irrlicht device and irrklang engine drop");
	log("Coeur closed");
	base::close();
	mylogger->close();
	device->drop();
	engine->drop();
	return 1;
}

int coeur::setCaption(stringw caption)
{
	device->setWindowCaption(caption.c_str());
	log(stringc("Change window caption to ") + caption.c_str());
	return 1;
}

IAnimatedMeshSceneNode* coeur::addMesh(stringc pathm)
{
	IAnimatedMesh* mesh = smgr->getMesh(pathm.c_str());
	if (!mesh)
		return 0;

	IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode(mesh);
	node->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true);
	node->setFrameLoop(0, 0);
	node->setLoopMode(false);

	ITriangleSelector* selector = smgr->createOctTreeTriangleSelector(mesh, node);
	metaSelector->addTriangleSelector(selector);
	selector->drop();

	

	if (!node)
		return 0;
	log(stringc("New mesh added : \"") + pathm + "\" number of frame :" + node->getEndFrame());
	return node;
}

ITexture* coeur::loadTexture(stringc path)
{
	log(stringc("Load texture ") + path);
	return driver->getTexture(path.c_str());
}

dimension2d<s32> coeur::getDim()
{
	return dim;
}

actionMesh *coeur::getSelectedAction()
{
	return selectedAction;
}

position2d<s32> coeur::getCurPos()
{
	return curPos;
}

u32 coeur::getTime()
{
	return device->getTimer()->getRealTime();
}


int coeur::play(stringc path)
{
	log(stringc("Play sound ") + path);
	engine->play2D(path.c_str(), false);
	return 1;
}

bool coeur::OnEvent(const SEvent& event)
{
	if (co->OnEvent(event))
		return false;
	if (event.EventType==EET_KEY_INPUT_EVENT)
	{
		if (event.KeyInput.PressedDown)
		{
			switch(event.KeyInput.Key)
			{
			case KEY_KEY_Q:
				q = true;
				return true;
				break;
			case KEY_KEY_M:
				cam->setInputReceiverEnabled(false);
				return true;
				break;
			default:
				break;
			}
		}
		else if (event.KeyInput.Key == KEY_KEY_M)
		{
			cam->setInputReceiverEnabled(true);
			return true;
		}
	}
	if (in->OnEvent(event))
		return true;
	return false;
}

int coeur::loadChap(int i)
{
	if (currentChap->isInit())
		currentChap->close();
	IXMLReader* xmlChap = device->getFileSystem()->createXMLReader((*pathChap)[i]->c_str());
	int numLieu = currentChap->init(i,this,xmlChap);
	xmlChap->drop();
	log(stringc("Chap ") + i + " load");

	loadLieu(numLieu);

	return 1;
}

int coeur::loadLieu(int i)
{
	if (currentLieu->isInit())
		currentLieu->close();
	IXMLReader* xmlLieu = device->getFileSystem()->createXMLReader((*pathLieu)[i]->c_str());
	currentLieu->init(i,this,xmlLieu);
	xmlLieu->drop();

	log(stringc("Lieu ") + i + " load");

	return 1;
}

int coeur::loadLocal(int i)
{
	if (currentLocal->isInit())
		currentLocal->close();
	IXMLReader* xmlLocal = device->getFileSystem()->createXMLReader((*pathLocal)[i]->c_str());
	currentLocal->init(i,this,xmlLocal);
	xmlLocal->drop();

	log(stringc("Local ") + i + " load");

	return 1;
}

item* coeur::getItem(int id)
{
	return currentChap->getItemFromId(id);
}

actionMesh* coeur::getActionMesh(int id)
{
	return currentLieu->getActionMesh(id);
}

actionMesh* coeur::getActionMesh(ISceneNode * node)
{
	return currentLieu->getActionMesh(node);
}

localItem* coeur::getObservationMesh(int id)
{
	return  currentLocal->getObservationMesh(id);
}

localItem* coeur::getObservationItem(int id)
{
	return  currentLocal->getObservationItem(id);
}

localItem* coeur::getCombinaison()
{
	return  currentLocal->getCombinaison();
}

logger* coeur::getLogger()
{
	return mylogger;
}


